package cn.iocoder.yudao.module.infrastructure.wechat.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.Assertions;
import cn.iocoder.yudao.framework.common.exception.KnownServiceException;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.api.infrastructure.social.SocialUserApi;
import cn.iocoder.yudao.module.api.infrastructure.social.dto.SocialUserRespDTO;
import cn.iocoder.yudao.module.api.infrastructure.social.enums.SocialTypeEnum;
import cn.iocoder.yudao.module.api.infrastructure.wechat.enums.WxTempateSceneEnum;
import cn.iocoder.yudao.module.api.infrastructure.wechat.enums.WxTempateTypeEnum;
import cn.iocoder.yudao.module.infrastructure.wechat.dao.WechatTemplateMapper;
import cn.iocoder.yudao.module.infrastructure.wechat.pojo.po.WechatTemplate;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;

import java.util.Map;

/**
 * 微信消息
 *
 * @author yshop
 * @author 山野羡民
 */
@Slf4j
abstract class WechatBaseMessageService {
    protected static final String REMARK = "我们将竭诚为您服务，若有疑问可联系平台客服。";

    @Resource
    private WechatTemplateMapper wechatTemplateMapper;

    @Resource
    private SocialUserApi socialUserApi;

    @Resource
    private WxMpService wxMpService;
    @Resource
    private WxMaService wxMaService;

    protected void sendWxMpTemplateMessage(Long userId, WxTempateSceneEnum sceneEnum, Map<String, String> parameters) {
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(getUserOpenid(userId))
                .templateId(getTemplateId(WxTempateTypeEnum.TEMPLATE, sceneEnum))
                .build();
        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            templateMessage.addData(new WxMpTemplateData(entry.getKey(), entry.getValue(), "#000000"));
        }
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (WxErrorException e) {
            log.error("【{}】发送失败", WxTempateTypeEnum.TEMPLATE.getName(), e);
            throw new KnownServiceException(e.getError().getErrorMsg());
        }
    }

    /**
     * 构建小程序一次性订阅消息
     *
     * @param userId 用户编号
     * @param sceneEnum 场景
     * @param page 跳转页面
     * @param parameters 模板参数内容
     */
    protected void sendWxMaSubscribeMsg(Long userId, WxTempateSceneEnum sceneEnum, String page, Map<String, String> parameters) {
        WxMaSubscribeMessage subscribeMessage = WxMaSubscribeMessage.builder()
                .toUser(getUserOpenid(userId))
                .templateId(getTemplateId(WxTempateTypeEnum.SUBSCRIBE, sceneEnum))
                .page(page)
                .build();
        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            subscribeMessage.addData(new WxMaSubscribeMessage.MsgData(entry.getKey(), entry.getValue()));
        }
        try {
            wxMaService.getMsgService().sendSubscribeMsg(subscribeMessage);
        } catch (WxErrorException e) {
            log.error("【{}】发送失败", WxTempateTypeEnum.SUBSCRIBE.getName(), e);
            throw new KnownServiceException(e.getError().getErrorMsg());
        }
    }

    @TenantIgnore
    private String getTemplateId(WxTempateTypeEnum typeEnum, WxTempateSceneEnum sceneEnum) {
        WechatTemplate wechatTemplateDO = wechatTemplateMapper.selectOne(
                WechatTemplate::getType, typeEnum.getCode(),
                WechatTemplate::getTempkey, sceneEnum.getCode()
        );
        Assertions.notNull(wechatTemplateDO, "请先在后台配置场景编码为【" + sceneEnum.getCode() + "】的微信" + typeEnum.getName() + "模板");
        Assertions.isTrue(CommonStatusEnum.isEnable(wechatTemplateDO.getStatus()), "微信" + typeEnum.getName() + "模板【" + wechatTemplateDO.getName() + "】已被禁用");
        return wechatTemplateDO.getTempid();
    }

    @TenantIgnore
    private String getUserOpenid(Long userId) {
        SocialUserRespDTO socialUserRespDTO = socialUserApi.getSocialUserByUserId(UserTypeEnum.MEMBER.getValue(), userId, SocialTypeEnum.WECHAT_MINI_PROGRAM.getType());
        Assertions.isTrue(socialUserRespDTO != null && StrUtil.isNotBlank(socialUserRespDTO.getOpenid()), "未获取到指定用户(ID#" + userId + ")的微信OpenId，无法发送微信消息通知");
        return socialUserRespDTO.getOpenid();
    }

}
